#include "los_config.h"
#include "ohos_init.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>

#include "display_typing_hw.h"

static const uint8_t g_displayBitmap[832] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0x7F, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x3F, 0xFF, 0x81, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x9F, 0xFF, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1D, 0x9F, 0xFE, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x9F, 0xFE, 0x03, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x3F, 0xFC, 0x03, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x9F, 0x88, 0x01, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0xBE, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x9C, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x98, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFA, 0x00, 0x00, 0x05, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x18, 0xC0, 0x60, 0x31, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0xF6, 0xC3, 0xFC, 0x36, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x36, 0xC3, 0xFC, 0x36, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0xFE, 0x83, 0xFC, 0x17, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x9D, 0x8F, 0xFF, 0x1B, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0x7F, 0xCC, 0xF3, 0xBF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x3F, 0xCF, 0xFF, 0xBF, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0xDF, 0xDF, 0xFF, 0xFF, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x9F, 0x91, 0xF8, 0xDF, 0xC7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1E, 0x3F, 0xD8, 0x01, 0xBF, 0x97, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1C, 0x9F, 0xEC, 0xF3, 0x7F, 0xB7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF4, 0x63, 0xFF, 0xC3, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF6, 0x06, 0xFF, 0xEF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0x07, 0xFE, 0x0F, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFE, 0x07, 0xFF, 0x87, 0xF7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF8, 0x3E, 0x77, 0xC1, 0xC7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF0, 0x78, 0x71, 0xF0, 0xF7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF1, 0xF0, 0xF8, 0xFC, 0x83, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xE0, 0xE0, 0x08, 0x70, 0x7F, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xE0, 0x60, 0x04, 0x60, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x97, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF0, 0x80, 0x00, 0x10, 0xC7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xE1, 0xC0, 0xF0, 0x38, 0xD7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xF3, 0x80, 0xF0, 0x19, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC1, 0xF8, 0x3F, 0xFF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC3, 0xFC, 0x3F, 0xC7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0x87, 0xFE, 0x1F, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC7, 0xFE, 0x3F, 0x9B, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x93, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0xC0, 0x1F, 0xFF, 0x00,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xC7, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCF, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xDF, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xF0,
    0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0x00
};

static void DisplayTypingDemo_SetPixel(uint8_t *frameBuffer, uint8_t x, uint8_t y, bool on)
{
    if ((frameBuffer == NULL) || (x >= DISPLAY_TYPING_SCREEN_WIDTH) ||
        (y >= DISPLAY_TYPING_SCREEN_PAGES * 8)) {
        return;
    }

    const uint16_t index = (y / 8U) * DISPLAY_TYPING_SCREEN_WIDTH + x;
    const uint8_t mask = 1U << (y % 8U);
    if (on) {
        frameBuffer[index] |= mask;
    } else {
        frameBuffer[index] &= ~mask;
    }
}

static void DisplayTypingDemo_ShowGreeting(void)
{
    static uint8_t frameBuffer[DISPLAY_TYPING_SCREEN_WIDTH * DISPLAY_TYPING_SCREEN_PAGES] = {0};
    memset(frameBuffer, 0, sizeof(frameBuffer));
    const uint8_t width = 100;
    const uint8_t height = 64;
    const uint8_t offsetX = 14;
    const uint8_t offsetY = 0;
    const uint8_t stride = (width + 7U) / 8U;

    for (uint8_t row = 0; row < height; ++row) {
        const uint8_t *rowData = &g_displayBitmap[row * stride];
        for (uint8_t col = 0; col < width; ++col) {
            const uint8_t byteVal = rowData[col / 8U];
            const bool pixelOn = (byteVal & (0x80U >> (col % 8U))) != 0;
            if (pixelOn) {
                DisplayTypingDemo_SetPixel(frameBuffer, offsetX + col, offsetY + row, true);
            }
        }
    }

    DisplayTypingDemo_Ssd1306FlushFull(frameBuffer, sizeof(frameBuffer));
}

unsigned int LosAppInit(void)
{
    DisplayTypingDemo_Ssd1306Init();
    if (!DisplayTypingDemo_IsInitialized()) {
        printf("Hello LiteOS display typing demo init failed: I2C not ready.\n");
        return LOS_NOK;
    }
    DisplayTypingDemo_ShowGreeting();
    printf("你好，世界 from LiteOS display typing demo!\n");
    return LOS_OK;
}

static void DisplayTypingDemoEntrypoint(void)
{
    (void)LosAppInit();
}

SYS_RUN(DisplayTypingDemoEntrypoint);
